home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / sox.zip / PRED.C < prev    next >
C/C++ Source or Header  |  1992-06-15  |  5KB  |  251 lines

  1.  
  2. /*
  3.  * July 5, 1991
  4.  * Copyright 1991 Lance Norskog And Sundry Contributors
  5.  * This source code is freely redistributable and may be used for
  6.  * any purpose.  This copyright notice must be maintained. 
  7.  * Lance Norskog And Sundry Contributors are not responsible for 
  8.  * the consequences of using this software.
  9.  */
  10.  
  11. /*
  12.  * Sound Tools prediction-correction compression effect file.
  13.  * Experiment with various simple equation systems.
  14.  * 
  15.  * This is not ready for prime time.  It's here for research purposes.
  16.  * Sox will hang if you run this as is.  Define D0 or D1, recompile,
  17.  * and try compressing the output with 'compress' and 'pack'.  
  18.  *
  19.  * Inspired by 2D PC gem in Graphics Gems II.
  20.  */
  21.  
  22. #include "st.h"
  23.  
  24. #define    D0    /* output difference between successive samples */
  25. /* #define    D1    /* guess by extending slope of last two samples */
  26. /* #define    D2     /* extend second derivate and guess signal turn */
  27. /* Autocorrelation isn't worth pursuing.  D2 should do an excellent job */
  28.  
  29. /* Private data for Prediction-Correction state machine */
  30. typedef struct predstuff {
  31.     int    direction;        /* 0 for compress, 1 for decompress */
  32.     int    first;            /* first time through? */
  33.     u_i    error;            /* average error output */
  34.     int    clipped;        /* # of clipped error values */
  35. #ifdef    D0 
  36.     long    in[1];            /* previous input sample */
  37. #endif
  38. #ifdef    D1
  39.     long    in[2];            /* previous input samples */
  40. #endif
  41. } *pred_t;
  42.  
  43. long pred_init(), pred_ict(), pred_next();
  44.  
  45. /*
  46.  * Process options
  47.  */
  48. pred_getopts(effp, n, argv) 
  49. eff_t effp;
  50. int n;
  51. char **argv;
  52. {
  53.     pred_t pred = (pred_t) effp->priv;
  54.  
  55.     if ((n != 1) || 
  56.             (strcmp(argv[0], "-c") && strcmp(argv[0], "-d")))
  57.         fail("Linp compression requires in or out options.");
  58.  
  59.     pred->direction = strcmp(argv[0], "-c");
  60. }
  61.  
  62. /*
  63.  * Start processing
  64.  */
  65. pred_start(effp)
  66. eff_t effp;
  67. {
  68.     pred_t pred = (pred_t) effp->priv;
  69.  
  70.     pred->error = 0;
  71.     pred->first = 1;
  72.     pred->clipped = 0;
  73. }
  74.  
  75. /*
  76.  * Process according to compression direction.
  77.  * Both loops use the same state machine, 
  78.  * but feed it from different streams.
  79.  */
  80. /*
  81.  * If first time, emit first two samples.
  82.  * Then,
  83.  */
  84.  
  85. pred_flow(effp, ibuf, obuf, isamp, osamp)
  86. eff_t effp;
  87. long *ibuf, *obuf;
  88. int *isamp, *osamp;
  89. {
  90.     int len, done;
  91.     pred_t pred = (pred_t) effp->priv;
  92.     register long predict, error;
  93.     
  94.     char c;
  95.     unsigned char uc;
  96.     short s;
  97.     unsigned short us;
  98.     long l;
  99.     unsigned long ul;
  100.     float f;
  101.     double d;
  102.  
  103.     done = 0;
  104.     if (pred->first) {
  105.         done = pred_init(effp, ibuf, obuf);
  106.         ibuf += done;
  107.         obuf += done;
  108.         pred->first = 0;
  109.     }
  110.     len = ((*isamp > *osamp) ? *osamp : *isamp);
  111.     if (done > len)        /* it can't happen here */
  112.         fail("Prediction effect: not enough samples?");
  113.     if (pred->direction) {            /* decompress */
  114.         for(; done < len; done++) {
  115.             /* reconstitute sample from prediction and error */
  116.             predict = pred_ict(effp);
  117.             error = *ibuf;
  118.             pred_next(effp, predict + error);
  119.             pred->error = pred->error/2 + abs(error)/2;
  120.             *obuf++ = predict + error;
  121.             ibuf++;
  122.         }
  123.     } else {                /* compress */
  124.         for(; done < len; done++) {
  125.             /* generate sample from prediction and error */
  126.             predict = pred_ict(effp);
  127.             error = *ibuf - predict;
  128.             pred->error = pred->error/2 + abs(error)/2;
  129.             if (predict + error != *ibuf)
  130.                 pred->clipped++;
  131.             pred_next(effp, *ibuf);
  132.             ibuf++;
  133.             *obuf++ = error;
  134.         }
  135.     }
  136. }
  137.  
  138. /* 
  139.  * Linear Prediction state machine part A.
  140.  * 
  141.  * Initialize from buffer.  Return number of samples processed.
  142.  * It will be the same for input and output streams.
  143.  */
  144. long
  145. pred_init(effp, ibuf, obuf)
  146. eff_t effp;
  147. long *ibuf, *obuf;
  148. {
  149.     pred_t pred = (pred_t) effp->priv;
  150.     long avg, ret;
  151.  
  152.     /* 
  153.      * This is bogus!  
  154.      * Just pretend samples in negative time are 0, make a first few
  155.      * weird guesses.
  156.      */
  157. #ifdef    D0
  158.     /* same for compress and decompress */
  159.     pred->in[0] = *obuf++ = *ibuf++;
  160.     return 1;
  161. #endif
  162. #ifdef    D1
  163.     /* same for compress and decompress */
  164.     pred->in[0] = *obuf++ = *ibuf++;
  165.     pred->in[1] = *obuf++ = *ibuf++;
  166.     return 2;
  167. #endif
  168. }
  169.  
  170. /* 
  171.  * Linear Prediction state machine part B.
  172.  * 
  173.  * Emit a predicted sample.
  174.  */
  175. long
  176. pred_ict(effp)
  177. eff_t effp;
  178. {
  179.     pred_t pred = (pred_t) effp->priv;
  180.     long avg, ret;
  181.  
  182. #ifdef    D1
  183.     avg = (pred->in[0]/2 + pred->in[1]/2);
  184.     return pred->in[1] + (pred->in[1] - avg);
  185. #endif
  186. #ifdef    D0
  187.     /* Assume flat data */
  188.     return pred->in[0];
  189. #endif
  190. }
  191.  
  192. /* 
  193.  * Linear Prediction state machine, part C.
  194.  * 
  195.  * Process next sample.
  196.  */
  197. long
  198. pred_next(effp, samp)
  199. eff_t effp;
  200. long samp;
  201. {
  202.     pred_t pred = (pred_t) effp->priv;
  203.     long avg, ret;
  204.  
  205. #ifdef    D1
  206.     pred->in[0] = pred->in[1];
  207.     pred->in[1] = samp;
  208. #endif
  209. #ifdef    D0
  210.     /* Assume flat data */
  211.     pred->in[0] = samp;
  212. #endif
  213. }
  214.  
  215. /*
  216.  * Do anything required when you stop reading samples.  
  217.  * Don't close input file! 
  218.  */
  219. pred_stop(effp)
  220. eff_t effp;
  221. {
  222.     pred_t pred = (pred_t) effp->priv;
  223.     int error;
  224.     int size;
  225.  
  226.     /* XXX Or should it always be the input size? */
  227.     if (pred->direction)
  228.         size = effp->ininfo.size;
  229.     else
  230.         size = effp->outinfo.size;
  231.     switch(size) {
  232.         case WORD:
  233.             error = pred->error / (1 << 16);
  234.             break;
  235.         case BYTE:
  236.             error = pred->error / (1 << 24);
  237.             break;
  238.         default:
  239.             error = pred->error;
  240.             break;
  241.     }
  242.     /* nothing to do */
  243.     fprintf(stderr, "Prediction\n\tAverage Error outputs: %d\n", error);
  244.     fprintf(stderr, "\tClipped error outputs: %d\n", pred->clipped);
  245. }
  246.  
  247.  
  248.  
  249.  
  250.  
  251.